package ascensor;

/**
 * Aca se definen e implementan las funciones que utiliza la interfaz grafica 
 */
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

//import java.awt.event.ActionEvent;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
//import java.io.UnsupportedEncodingException;
//import java.nio.ByteBuffer;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TooManyListenersException;

//import javax.swing.Action;
//import javax.swing.JTextArea;
//import javax.swing.JTextField;

//import com.sun.xml.internal.ws.util.ASCIIUtility;

//import java.util.HashSet;

public class TwoWaySerialComm
{

	public TwoWaySerialComm()
	{
		super();

	}

	// PUERTO QUE SE VA A ABRIR
//	private static final String PORT_NAMES[] = { "/dev/ttyUSB0",
//			"/dev/ttyUSB1", "/dev/ttyUSB2", "/dev/ttyUSB3", };

	static OutputStream outputStream;
	// static String messageString = "ON01";

	static SerialPort PUERTOCERRAR;
	static SerialPort serialPort;

	// static Enumeration portList;
	static CommPortIdentifier portId;
	static CommPortIdentifier portIdentifier;
	// static CommPort commPort;
	static InputStream in;
	/**
	 * para la lectura de un archivo
	 */
	// Variables leidas del archivo de configuracion
	private static final String BaudRate = TwoWaySerialComm
			.LeerArchivoConfig("baudrate");
	private static final String Bitsdatos = TwoWaySerialComm
			.LeerArchivoConfig("bitsdatos");
	private static final String Bitsparada = TwoWaySerialComm
			.LeerArchivoConfig("bitsparada");
	private static final String Paridad = TwoWaySerialComm
			.LeerArchivoConfig("paridad");
	static final String defaultPort = TwoWaySerialComm
			.LeerArchivoConfig("puerto");

	// static int delay = 0; // delay for 0 sec.

	static int delay = Integer.valueOf(TwoWaySerialComm
			.LeerArchivoConfig("retinicio"));
	static int period = Integer.valueOf(TwoWaySerialComm
			.LeerArchivoConfig("delams"));

	static int CantidadPlacas = Integer.valueOf(TwoWaySerialComm
			.LeerArchivoConfig("cantplaca"));
	static int CantidadPisos = Integer.valueOf(TwoWaySerialComm
			.LeerArchivoConfig("cantpisos"));

	static Timer timer = new Timer();

	/*
	 * static final String periodo =
	 * TwoWaySerialComm.LeerArchivoConfig("delams"); static int period1 =
	 * Integer.valueOf(periodo); // repeat every 500 msec.
	 * 
	 * static int period = period1; //500; // delay for 0 sec.//
	 */

	static int contador = 1;
	private static byte[] readBuffer = new byte[400];
	private static int[] BufferLectura = new int[400];

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * @param portName
	 * @throws Exception
	 *             Abre el puerto e inicializa de acuerdo a los valores leidos
	 *             del archivo de configuracion
	 */
	static void connect(String portName) throws Exception
	{
		/*
		 * CommPortIdentifier portIdentifier = CommPortIdentifier
		 * .getPortIdentifier(portName);//
		 */
		portIdentifier = CommPortIdentifier.getPortIdentifier(portName);

		if (portIdentifier.isCurrentlyOwned())
		{
			System.out.println("Error: Port is currently in use");
		} else
		{
			/*
			 * CommPort commPort =
			 * portIdentifier.open(this.getClass().getName(), 2000); //
			 */
			CommPort commPort = portIdentifier.open("SimpleWrite", 2000);
			// commPort = portIdentifier.open("SimpleWrite",2000);
			if (commPort instanceof SerialPort)
			{
				// SerialPort serialPort = (SerialPort) commPort;
				serialPort = (SerialPort) commPort;
				/*
				 * serialPort = (SerialPort) portIdentifier.open("SimpleWrite",
				 * 2000);//
				 */

				try
				{
					outputStream = serialPort.getOutputStream();
				} catch (IOException e)
				{
				}

				serialPort.setSerialPortParams(Integer.valueOf(BaudRate),
						Integer.valueOf(Bitsdatos),
						Integer.valueOf(Bitsparada), Integer.valueOf(Paridad));
				/*
				 * serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
				 * SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);//
				 */

				// InputStream in = serialPort.getInputStream();
				in = serialPort.getInputStream();
//				OutputStream out = serialPort.getOutputStream();

				/*
				 * (new Thread(new SerialReader(in))).start(); (new Thread(new
				 * SerialWriter(out))).start();//
				 */

				try
				{
					serialPort.notifyOnOutputEmpty(true);
				} catch (Exception e)
				{
					System.out.println("Error setting event notification");
					System.out.println(e.toString());
					System.exit(-1);
				}

			} else
			{
				System.out
						.println("Error: Only serial ports are handled by this example.");
			}
			System.out.println("puerto Abierto " + portName);
		}
	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * cierra el puerto
	 * 
	 * @param portName
	 * @throws Exception
	 */
	// public static void CerrarPuerto(String portName) throws Exception
	public static void CerrarPuerto() throws Exception
	{
		// defaultPort = portName;
		System.out.println("Tratando de cerrar el puerto");
		// portList = CommPortIdentifier.getPortIdentifiers();
		portId = portIdentifier;

		if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)
		{
			System.out.println("Found port " + portId.getName());
			PUERTOCERRAR = serialPort;

			try
			{
				outputStream = PUERTOCERRAR.getOutputStream();
			} catch (IOException e)
			{
				System.out.println("ERROR");
			}
			/*
			 * try { PUERTOCERRAR.setSerialPortParams(9600,
			 * SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
			 * SerialPort.PARITY_NONE); } catch
			 * (UnsupportedCommOperationException e) {}
			 * 
			 * //
			 */
			try
			{
				PUERTOCERRAR.notifyOnOutputEmpty(true);
			} catch (Exception e)
			{
				System.out.println("Error setting event notification");
				System.out.println(e.toString());
				System.exit(-1);
			}

			try
			{
				Thread.sleep(2000); // Be sure data is xferred before closing
			} catch (Exception e)
			{
			}

			PUERTOCERRAR.close();
			System.out.println("PUERTO CERRADO");
			System.exit(1);

		}

	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * Funciones que se usan para leer el puerto USB
	 */
	private static void readSerial()
	{
		int len = 0;
		int data = 0;
		try
		{
			int availableBytes = in.available();

			if (availableBytes > 0)
			{

				while ((data = in.read()) > 1)
				{
					if (data == '\n')
					{
						break;
					}
					//readBuffer[len] = (byte) data;//A borrar
					
					BufferLectura[len] = data;
					len++;//A borrar
					//System.out.println(data);
				}
				// Imprimir lo que llega

				/**
				 * si llegan datos de lectura del puerto
				 */
				 /*String Imprimir = new String(readBuffer);//A borrar
				 System.out.println(Imprimir); //A borrar//*/
				if (BufferLectura[0] == '\r') //si el primer valor recibido indica que es una lectura de puerto
				{
					int leido = BufferLectura[1] - 48;
					System.out.println(leido);
				}//*/

				if (BufferLectura[0] == '\t') //si el primer valor recibido indica que es una lectura de puerto
				{
					
					Analizar(BufferLectura,len);
					//la posicion [1] indica el puerto leido
					//System.out.println((char)BufferLectura[1]);
					/*System.out.println(Integer.toString(BufferLectura[1])+" ");
					//System.out.println( Integer.toBinaryString(BufferLectura[1]));
					System.out.print(BufferLectura[2]+" ");
					System.out.println(Integer.toBinaryString(BufferLectura[2]));
					System.out.print(BufferLectura[3]+" ");
					System.out.println( Integer.toBinaryString(BufferLectura[3]));
					//System.out.println(BufferLectura[3]);//*/
				}//*/

			}
		} catch (IOException e)
		{
		}// */

		for (data = 0; data <= len; ++data)
		{
			BufferLectura[data] = 0;
			readBuffer[data] = 0;
		}

		/*
		 * esto es el codigo que tambien funciona int len = 0; int data = 0; try
		 * { int availableBytes = in.available(); //
		 * System.out.println("tratando de leer"); if (availableBytes > 0) {
		 * 
		 * while()
		 * 
		 * 
		 * 
		 * // Leer el puerto in.read(readBuffer, 0, availableBytes); // Imprimir
		 * lo que llega System.out.println(new String(readBuffer, 0,
		 * availableBytes)); // System.out.println("puerto Leido"); } } catch
		 * (IOException e) { }
		 */
	}

	/**
	 * 
	 * @author laboratorio Esto es para implementar como un THREAD
	 */
	/*
	 * 
	 * private class ReadThread implements Runnable { public void run() { while
	 * (true) { readSerial(); } } }
	 * 
	 * public void setSerialListener() { new Thread(new ReadThread()).start(); }
	 * //
	 */

	/**
	 * Esto es para implementar como un evento
	 * 
	 */

	private class SerialEventHandler implements SerialPortEventListener
	{
		public void serialEvent(SerialPortEvent event)
		{
			switch (event.getEventType())
			{
			case SerialPortEvent.DATA_AVAILABLE:
				readSerial();
				break;
			}
		}
	}

	/**
	 * Set the serial event handler
	 */
	private void setSerialEventHandler(SerialPort serialPort1)
	{
		try
		{
			// Add the serial port event listener
			serialPort1.addEventListener(new SerialEventHandler());
			serialPort1.notifyOnDataAvailable(true);
		} catch (TooManyListenersException ex)
		{
			System.err.println(ex.getMessage());
		}
	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * Funcion que escribe una cadena en el puerto
	 * 
	 * 
	 */
	public static void EscribirPuerto(String messageString)
	{
		// System.out.println(messageString);
		try
		{
			outputStream.write(messageString.getBytes());
		} catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * Funcion para la lectura del puerto!
	 * 
	 * @return
	 */
	public static void LeerPuerto(int Puerto)
	{
		EscribirPuerto("OPX" + Puerto);
		//readSerial();

	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * @return A HashSet containing the CommPortIdentifier for all serial ports
	 *         that are not currently being used. Obtiene todos los puertos
	 *         disponible NO SE USA
	 */
	/*
	 * public static HashSet<CommPortIdentifier> getAvailableSerialPorts() {
	 * HashSet<CommPortIdentifier> h = new HashSet<CommPortIdentifier>();
	 * Enumeration thePorts = CommPortIdentifier.getPortIdentifiers(); while
	 * (thePorts.hasMoreElements()) { CommPortIdentifier com =
	 * (CommPortIdentifier) thePorts .nextElement();
	 * 
	 * for (String portName : PORT_NAMES) {
	 * 
	 * if (com.getName().equals(portName)) { defaultPort = com.getName();
	 * System.out.println("puerto Encontrado " + defaultPort); }
	 * 
	 * }
	 * 
	 * } return h; // verificar si no esta de mas!
	 * 
	 * }//
	 */// String cadena = "thelma";

	// -----------------------------------------------------------------------------------------------------------------------------

	/**
	 * Para leer el archivo lee el archivo en el directorio actual con el nombre
	 * de MyReadFile Necesita un String con el nombre de la cadena a leer
	 * Devuelve un String con el valor leido
	 * 
	 * @return
	 */
	public static String LeerArchivoConfig(String ValorLeer)
	{
		String ValorLeido = null;
		try
		{
			// abriendo el archivo
			FileInputStream propFile = new FileInputStream("MyReadFile");
			Properties p = new Properties(System.getProperties());
			p.load(propFile);

			System.setProperties(p);
			// System.getProperties().list(System.out);
			// System.getProperties(p);

			ValorLeido = System.getProperty(ValorLeer);// */
		} catch (java.io.FileNotFoundException e)
		{
			System.out.println("err1 " + e);
			;
		} catch (java.io.IOException e)
		{
			System.out.println("err2");
			;
		}// */
		return ValorLeido;
	}

	// --------------------------------------------------------------------------------------------------------------------------------
	/**
	 * Analizador de estado de los puertos segun los datos leidos pasa como
	 * parametro el buffer de Byte leido y la cantidad leida, en si espera
	 * caracteres Ascii con representacion HEX
	 */

	private static void Analizar(int[] Cadena, int len)
	{
		/**
		 * Las 2 primeras posiciones NO se deben analizar 0 y 1
		 * Las 2 siguientes contienen los datos que necesitamos saber!
		 */
		int placa = (char)Cadena[1] - 48; //obtengo el nro de la placa que me envia
		int piso = 0; 
		int Seleccion1 = 0;
		int Seleccion2 = 0;
		switch(placa)
		{
		 case 1: piso = 0;
		 break;
		 case 3: piso = 16;
		 break;
		 case 5: piso = 32;
		 break;
		 case 7: piso = 48;
		 break;
		}
		String cadenaanterior=" ";		
		//ascensor.NewJFrame.jAreaTexto1.setText(" ");
		//System.out.println(Cadena[2]);				
		/**
		 * Comentado para probar cambio en el micro
		 */
		/*
		if (contador < 9) // Las placas estan numeradada 1 - 3 - 5 - 7
							// (asi se lee integrado 0 y 1 - 2 y 3 - 4 y
							// 5 - 6 y 7)
		{
			// System.out.println(contador);
			LeerPuerto(contador);
			contador = contador + 2;
			//System.out.println(contador);
		
		} else
		{
			contador = 1;
		}//*/
		/*
		//tratar de leer todos los puertos al mismo tiempo
		for(int r = 1; r<9; r++)
		{
			System.out.println(r);
			//timer.cancel();
			LeerPuerto(r);
			//timer.
			r++;
			//System.out.println(r);
		}//*/
		for (int u = 0; u<8;++u)
		{
			if ((Cadena[2] & (1L << u)) == 0)
			{	
				Seleccion1=u+1+piso;
				System.out.println("el piso " + (Seleccion1) + " esta solicitado ");
				cadenaanterior = ascensor.NewJFrame.jAreaTexto1.getText();
				ascensor.NewJFrame.jAreaTexto1.setText(cadenaanterior+ "|" + Seleccion1);
			}
		}
		//System.out.println(Cadena[3]);

		for (int u = 0; u<8;++u)
		{
			if ((Cadena[3] & (1L << u)) == 0)
			{
				Seleccion2=u+9+piso;
				System.out.println("el piso " + (Seleccion2) + " esta solicitado ");
				cadenaanterior = ascensor.NewJFrame.jAreaTexto1.getText();
				ascensor.NewJFrame.jAreaTexto1.setText(cadenaanterior+ "|" + Seleccion2);
			}
		}//*/

	}

	// ------------------------------------------------------------------------------------------------------------------------------
	/**
	 * Inicializa el Timer de Lectura de Puerto
	 */
	public static void IniciarTimer()
	{
		// Timer timer = new Timer();

		timer.scheduleAtFixedRate(new TimerTask()
		{
			public void run()
			{
				// Accion a Realizar
				LeerPuerto(1); //solo para prueba del cambio del micro
				
				
				/**
				 * Comentado para probar cambio en el micro
				 */
				/*
				if (contador < 9) // Las placas estan numeradada 1 - 3 - 5 - 7
									// (asi se lee integrado 0 y 1 - 2 y 3 - 4 y
									// 5 - 6 y 7)
				{
					// System.out.println(contador);
					LeerPuerto(contador);
					contador = contador + 2;
					//System.out.println(contador);
				
				} else
				{
					contador = 1;
				}//*/
				/*
				//tratar de leer todos los puertos al mismo tiempo
				for(int r = 1; r<9; r++)
				{
					System.out.println(r);
					//timer.cancel();
					LeerPuerto(r);
					//timer.
					r++;
					//System.out.println(r);
				}//*/
			}
		}, delay, period);
	}// */

	// ------------------------------------------------------------------------------------------------------------------

	/**
	 * Main de ejecucion
	 * @param jAreaTexto2 
	 * @param jAreaTexto1 
	 * 
	 * @throws InterruptedException
	 * */
	public static void mainasd() throws InterruptedException
	{
		//
		TwoWaySerialComm main = new TwoWaySerialComm();
		// main.setSerialListener(); //Como un Thread
		System.out.println("1RO");
		main.setSerialEventHandler(serialPort); // como un evento
		/**
		 * Solo para verificar los datos leidos del archivo de configuracion
		 */
		/*
		 * System.out.println(BaudRate); System.out.println(Bitsdatos);
		 * System.out.println(Bitsparada); System.out.println(Paridad);
		 * System.out.println(defaultPort);//
		 */
		/*
		 * System.out.println(period); System.out.println(delay);
		 * System.out.println(CantidadPlacas);
		 * System.out.println(CantidadPisos);//
		 */

		/**
		 * TIMER que se ejecuta de acuerdo al tiempo leido del arch. de
		 * configuracion.
		 */
		IniciarTimer();
		//*/
		
	}

}